/*
 * Copyright (c) 2019-2025, Jason(yunho.top) All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the yunho.top developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Jason (yunho.top)
 *
 *
 */

package io.yunho.yunho.interview.two.juc;

import org.junit.jupiter.api.Test;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.TimeUnit;

/**
 * @author : Jason
 * @date : 2020/5/20 17:40
 * @description :集合类不安全案例
 * ArrayList
 * HashSet 同理
 *
 * java.util.ConcurrentModificationException 线程不安全的例证
 */
public class ContainerNotSafe {

//    public static void main(String[] args) {
//        Set<String> strings = new CopyOnWriteArraySet<>();
//        System.out.println("*******"+strings);
//        for(int i=0;i<30;i++){
//            new Thread(()->{
//                strings.add(UUID.randomUUID().toString().substring(0,8));
//                System.out.println(strings);
//            },String.valueOf(i)).start();
//        }
//    }
    @Test
    public void  testMap(){
        mapNotSafe();
    }

    private void mapNotSafe() {
//        Map<String,String> strings = new ConcurrentHashMap<>();
        //故障说明：java.util.ConcurrentModificationException
        Map<String,String> strings = new HashMap<>();

        System.out.println("*******"+strings);
        for(int i=0;i<1000;i++){
            new Thread(()->{
                strings.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0,8));
//                System.out.println(strings);
            },String.valueOf(i)).start();
        }
        try {
            TimeUnit.SECONDS.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}
//        System.out.println("*******"+strings);
        System.out.println("*******"+strings.size());
    }

    @Test
    public void testHashSet(){
        setNotSafe();
//        new HashSet<>().add("a");
    }

    private void setNotSafe() {
        Set<String> set = new HashSet<>();
        for(int i=0;i<50;i++){
            new Thread(()->{
                set.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(set);
            },String.valueOf(i)).start();
        }
//        Set<String> strings = new CopyOnWriteArraySet<>();
//        System.out.println("*******"+strings);
//        for(int i=0;i<30;i++){
//            new Thread(()->{
//                strings.add(UUID.randomUUID().toString().substring(0,8));
//                System.out.println(strings);
//            },String.valueOf(i)).start();
//        }
        try {
            TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}
    }

    @Test
    public void testListNotSafe(){
//        List<String> list = Arrays.asList("1","b","d");
//        list.forEach(System.out::println);
//
        List<String> list1 = new ArrayList<>();
        for(int i=0;i<50;i++){
            new Thread(()->{
            list1.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(list1);
            },String.valueOf(i)).start();
        }
        new HashMap<>();
        /**
         * 1 故障现象
         * java.util.ConcurrentModificationException 线程不安全的例证
         *
         *
         * 2 导致原因
         *  并发争抢修改导致
         * 一个人正在写，另一个人过来抢夺，导致数据不一致异常
         * 3 解决方案
         * 3.1 new Vector<>()  可以解决，但是它的版本是jdk1.0，而ArrayList诞生于1.2，可以想象不是最优方案，牺牲了并发性能，所以才会有后来的ArrayList
         * 3.2 Collections.synchronizedList(new ArrayList<>())
         * 3.3 new CopyOnWriteArrayList<>()
         *
         * 4 优化建议（同样的错误不犯第2次）
         */
        //3 ``
//        List<String> list2 = Collections.synchronizedList(new ArrayList<>());
//        for(int i=0;i<30;i++){
//            new Thread(()->{
//                list2.add(UUID.randomUUID().toString().substring(0,8));
////            list1.forEach(System.out::println);
//                System.out.println(list2);
//            },String.valueOf(i)).start();
//        }
//        List<String> list2 = new CopyOnWriteArrayList<>();
//        for(int i=0;i<30;i++){
//            new Thread(()->{
//                list2.add(UUID.randomUUID().toString().substring(0,8));
////            list1.forEach(System.out::println);
//                System.out.println(list2);
//            },String.valueOf(i)).start();
//        }
        try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}
    }
}

